# coding: utf-8
import numpy as np


def identity_function(x):
    return x


def step_function(x):
    return np.array(x > 0, dtype=np.int)


def sigmoid(x):
    return 1 / (1 + np.exp(-x))    


def sigmoid_grad(x):
    return (1.0 - sigmoid(x)) * sigmoid(x)
    

def relu(x):
    return np.maximum(0, x)


def relu_grad(x):
    grad = np.zeros_like(x)
    grad[x>=0] = 1
    return grad
    

def softmax(x):
    x = x - np.max(x, axis=-1, keepdims=True)   # オーバーフロー対策
    return np.exp(x) / np.sum(np.exp(x), axis=-1, keepdims=True)


def sum_squared_error(y, t):
    return 0.5 * np.sum((y-t)**2)

# 交叉熵误差
def cross_entropy_error(y, t):

    #  确保 t 和 y 都是二维数组，即使它们最初是一维数组
    # 这种转换是为了确保函数能够正确处理多维数组的情况，在机器学习中很常见
    if y.ndim == 1:
        t = t.reshape(1, t.size)
        y = y.reshape(1, y.size)
        
    # 教師データがone-hot-vectorの場合、正解ラベルのインデックスに変換
    if t.size == y.size:
        t = t.argmax(axis=1) # argmax是一个NumPy函数，用于返回数组中元素的最大值所在的索引位置
             
    batch_size = y.shape[0]
    # y[np.arange(batch_size), t] + 1e-7遍历每一行数组的第t个元素，广播加上1e-7，防止出现0
    # 这种方式在处理机器学习中的批量数据时特别有用，因为它允许你以一种简洁的方式访问数据集中的特定元素
    return -np.sum(np.log(y[np.arange(batch_size), t] + 1e-7)) / batch_size


def softmax_loss(X, t):
    y = softmax(X)
    return cross_entropy_error(y, t)
